/**
 * 京东联盟商品批量采集与详情补充模块
 * @version 1.0.0
 * @author 开发者
 * @see {@link https://union.jd.com/openplatform/api/1230|京东联盟API文档}
 */

const {
  normalizePayload,
  normalizeDbConfig,
  persistDocs,
  chunkArray,
  mapMergedGoodsDoc
} = require('./@utils')
const queryRankGoods = require('./queryRankGoods')
const queryGoodsBigfield = require('./queryGoodsBigfield')
const queryJingfenGoods = require('./queryJingfenGoods')
const queryMaterialGoods = require('./queryMaterialGoods')

/**
 * 商品批量采集与详情补充控制器
 *
 * 该函数用于批量采集指定数量的商品数据，并自动补充商品大字段详情。
 * 支持多种商品查询方法，包括实时热销榜、京粉精选、物料精选等。
 * 提供分页采集、批量详情查询和数据持久化功能。
 *
 * @param {object} payload 请求参数对象
 * @param {string} payload.appKey 京东联盟应用Key
 * @param {string} payload.appSecret 京东联盟应用密钥
 * @param {string} [payload.method='jd.union.open.goods.rank.query'] 商品查询方法，可选值：
 *   - 'jd.union.open.goods.rank.query': 实时热销榜
 *   - 'jd.union.open.goods.jingfen.query': 京粉精选
 *   - 'jd.union.open.goods.material.query': 物料精选
 * @param {number} [payload.totalCount=20] 需要采集的商品总数
 * @param {Record<string, any>} [payload.listParams] 商品列表查询参数
 * @param {number} [payload.detailSceneId] 详情查询场景ID
 * @param {number} [payload.detailChunkSize=10] 详情查询分块大小，取值范围1-10
 * @param {string[]} [payload.detailFields] 详情查询的字段域，可选：categoryInfo, imageInfo, baseBigFieldInfo, bookBigFieldInfo, videoBigFieldInfo, detailImages
 * @param {{enable?: boolean, collection?: string, extraDocFields?: Record<string, any>}} [payload.persistence] 数据持久化配置
 * @returns {Promise<{baseGoods: any[], detailGoods: any[], mergedGoods: any[], persistenceResult?: any}>} 采集结果
 * @throws {Error} 当参数验证失败或API请求失败时抛出错误
 * @example
 * // 采集20个实时热销榜商品并补充详情
 * const result = await collectGoodsWithDetails({
 *   appKey: 'your_app_key',
 *   appSecret: 'your_app_secret',
 *   method: 'jd.union.open.goods.rank.query',
 *   totalCount: 20,
 *   listParams: {
 *     pageSize: 10,
 *     cid1: 1315
 *   },
 *   detailSceneId: 1,
 *   detailChunkSize: 10
 * })
 *
 * @example
 * // 采集京粉精选商品并启用数据持久化
 * const result = await collectGoodsWithDetails({
 *   appKey: 'your_app_key',
 *   appSecret: 'your_app_secret',
 *   method: 'jd.union.open.goods.jingfen.query',
 *   totalCount: 50,
 *   listParams: {
 *     eliteId: 1,
 *     pageSize: 20
 *   },
 *   persistence: {
 *     enable: true,
 *     collection: 'jd_collected_goods',
 *     extraDocFields: {source: 'jingfen'}
 *   }
 * })
 *
 * @example
 * // 采集物料精选商品（猜你喜欢频道）
 * const result = await collectGoodsWithDetails({
 *   appKey: 'your_app_key',
 *   appSecret: 'your_app_secret',
 *   method: 'jd.union.open.goods.material.query',
 *   totalCount: 30,
 *   listParams: {
 *     eliteId: 400,
 *     pageSize: 15,
 *     userId: 'user123'
 *   },
 *   detailChunkSize: 15
 * })
 *
 * @example
 * // 仅采集商品列表，不补充详情
 * const result = await collectGoodsWithDetails({
 *   appKey: 'your_app_key',
 *   appSecret: 'your_app_secret',
 *   totalCount: 10,
 *   listParams: {
 *     pageSize: 10
 *   }
 * })
 */
async function collectGoodsWithDetails(payload) {
  const { auth, query, options } = normalizePayload(payload)

  const {
    method = 'jd.union.open.goods.rank.query',
    totalCount = 20,
    listParams = {},
    detailSceneId,
    detailChunkSize = 10,
    detailFields // 详情查询的字段域
  } = query

  if (!auth.appKey || !auth.appSecret) {
    throw new Error('appKey和appSecret不能为空')
  }

  const targetCount = Math.max(1, Number(totalCount) || 1)
  let pageIndex = listParams.pageIndex || 1
  const collected = []

  while (collected.length < targetCount) {
    let res
    if (method === 'jd.union.open.goods.rank.query') {
      const pageSize = Math.max(1, Math.min(listParams.pageSize || 20, 20)) // 默认20，最大20
      res = await queryRankGoods({
        auth,
        query: { ...listParams, pageIndex, pageSize },
        options: { ...options, db: undefined, debug: true } // 使用 debug 模式获取完整数据
      })
      const chunk = Array.isArray(res.queryResult?.data) ? res.queryResult.data : []
      collected.push(...chunk)
      if (chunk.length < pageSize) {
        break
      }
    } else if (method === 'jd.union.open.goods.jingfen.query') {
      const pageSize = Math.max(1, Math.min(listParams.pageSize || 50, 50)) // 默认50，最大50
      res = await queryJingfenGoods({
        auth,
        query: { ...listParams, pageIndex, pageSize },
        options: { ...options, db: undefined, debug: true }
      })
      const chunk = Array.isArray(res.queryResult?.data) ? res.queryResult.data : []
      collected.push(...chunk)
      if (chunk.length < pageSize) {
        break
      }
    } else if (method === 'jd.union.open.goods.material.query') {
      const pageSize = Math.max(1, Math.min(listParams.pageSize || 10, 10)) // 默认10，最大10
      res = await queryMaterialGoods({
        auth,
        query: { ...listParams, pageIndex, pageSize, includeBigfield: false },
        options: { ...options, db: undefined, debug: true }
      })
      const chunk = Array.isArray(res.queryResult?.data) ? res.queryResult.data : []
      collected.push(...chunk)
      if (chunk.length < pageSize) {
        break
      }
    } else {
      throw new Error(`暂不支持的method：${method}`)
    }
    pageIndex += 1
  }

  const baseGoods = collected.slice(0, targetCount)
  if (baseGoods.length === 0) {
    return {
      baseGoods: [],
      detailGoods: [],
      mergedGoods: []
    }
  }

  const itemIds = baseGoods.map((item) => item.itemId).filter(Boolean)
  const detailGoods = []
  const chunkSize = Math.max(1, Math.min(detailChunkSize, 10)) // 最大支持10
  for (const idsChunk of chunkArray(itemIds, chunkSize)) {
    const goodsReq = {
      itemIds: idsChunk
    }
    if (typeof detailSceneId === 'number') {
      goodsReq.sceneId = detailSceneId
    }
    if (Array.isArray(detailFields) && detailFields.length > 0) {
      goodsReq.fields = detailFields
    }
    const res = await queryGoodsBigfield({
      auth,
      query: { goodsReq },
      options: { ...options, db: undefined, debug: true } // 使用 debug 模式
    })
    const chunkDetails = Array.isArray(res.queryResult?.data) ? res.queryResult.data : []
    detailGoods.push(...chunkDetails)
  }

  const detailMap = new Map(detailGoods.map((item) => [item.itemId, item]))
  const mergedGoods = baseGoods.map((item) => ({
    ...item,
    bigfield: detailMap.get(item.itemId)
  }))

  let dbResult
  const dbConfig = normalizeDbConfig(options.db)
  if (dbConfig) {
    dbResult = await persistDocs({
      collectionName: dbConfig.collection,
      list: mergedGoods,
      transform: mapMergedGoodsDoc,
      uniqueKeys: dbConfig.uniqueKeys,
      extraDocFields: dbConfig.extraFields
    })
  }

  if (options.debug) {
    return {
      baseGoods,
      detailGoods,
      mergedGoods,
      dbResult
    }
  }

  // 返回合并后的商品数据
  return {
    code: 200,
    message: 'success',
    data: mergedGoods,
    totalCount: mergedGoods.length
  }
}

module.exports = collectGoodsWithDetails
